﻿using CommonUtils;
using SharpShell.Interop;
using SharpShell.SharpIconOverlayHandler;
using System;
using System.Drawing;

namespace GitIconOverlayHandlers
{
    public class GitIconOverlayHandler : SharpIconOverlayHandler
    {
        public virtual GitStatus StatusToMatch { get; }

        public const string Filed_WorkFolder = "GitIconOverlayorFolder";

        private static readonly string _workFolder = RegistryUtil.GetFromConfig(Filed_WorkFolder);

        /// <summary>
        /// 静态初始化
        /// </summary>
        static GitIconOverlayHandler()
        {
            //设置根目录，不设置的话，日志文件就不知道去哪了
            PathConfig.SetWorkFolder(_workFolder);
            LogUtil.Info("程序{0}初始化了GitIconOverlayHandler！", ApplicationUtil.ProcessName);
        }

        /// <summary>
        /// 初始化
        /// </summary>
        protected GitIconOverlayHandler() : base()
        {
            LogUtil.Info("程序{0}声明了一个状态为{1}的新GitIconOverlayHandler！", ApplicationUtil.ProcessName, StatusToMatch);
        }

        /// <summary>
        /// 获取图标覆盖优先级
        /// TortoiseIcons的优先级是100？100以上不打卡，100以下打卡
        /// RegistrationName的ASCII码排序决定了访问优先级,优先访问为true便不再往下执行
        /// </summary>
        protected override int GetPriority()
        {
            //LogUtil.Info("程序{0}正在获取状态{1}的优先级！", ApplicationUtil.ProcessName, StatusToMatch);

            return 99;
        }

        private static readonly string _iconsFolder = _workFolder.Combine("icons");

        protected override Icon GetOverlayIcon()
        {
            //LogUtil.Info("程序{0}正在获取状态{1}的图标！", ApplicationUtil.ProcessName, StatusToMatch);

            switch (StatusToMatch)
            {
                case GitStatus.Pushed:
                    return new Icon(_iconsFolder.Combine("Pushed.ico"));
                case GitStatus.Committed:
                    return new Icon(_iconsFolder.Combine("Committed.ico"));
                case GitStatus.Modified:
                    return new Icon(_iconsFolder.Combine("Modified.ico"));
                case GitStatus.Conflict:
                    return new Icon(_iconsFolder.Combine("Conflict.ico"));
                default://按照逻辑Status不会出现这种情况
                    LogUtil.Info("Has Bug !!!");
                    return new Icon(_iconsFolder.Combine("Unknown.ico"));
            }
        }

        private static readonly SafeMap<string, GitStatus> _fileList = new SafeMap<string, GitStatus>();

        public const GitStatus PrioritizedStatus = GitStatus.Pushed;

        private static readonly SafeMap<string, GitStatus> _statusMap = new SafeMap<string, GitStatus>();

        /// <summary>
        /// 方法对同一个状态是并发的，对不同状态是顺序的
        /// </summary>
        protected override bool CanShowOverlay(string path, FILE_ATTRIBUTE attributes)
        {
            //只操作资源管理器
            if (ApplicationUtil.ProcessName != "explorer")
                return false;

            try
            {
                //忽略文件夹会造成在克隆项目时混乱 所以这里只收录文件 虽然降效率了 没有太好的办法
                if (_fileList.Contains(path))
                    return false;

                //把优先级最高的结果缓存 低优先级直接读缓存
                if (StatusToMatch == PrioritizedStatus)
                {
                    var status = GitUtil.GetStatus(path);
                    if (status == GitStatus.NotGit && FileBasic.IsFile(path))
                    {
                        _fileList.Add(path);
                        return false;
                    }
                    _statusMap.Set(path, status);
                }

                return StatusToMatch == _statusMap.Get(path);
            }
            catch (Exception ex)
            {
                ex.HelpLink = string.Format("报错了！StatusToMatch:{0}\r\nVersion:{1}\r\nPath:{2}", StatusToMatch, ApplicationUtil.Version, path);
                LogUtil.Info(ex);
                return false;
            }
        }

        public bool GetIconOverlayState(string path)
        => CanShowOverlay(path, FILE_ATTRIBUTE.FILE_ATTRIBUTE_NORMAL);
    }
}
